using CfgTable;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Framework.Serialization;
using IQIGame.Onigao.Game;
using System;
#if !LOGIC_SERVER
using Cysharp.Threading.Tasks;
using UnityEngine;
#endif

namespace IQIGame.Onigao.GamePlay
{
    public static class TableCenter
    {
#if !LOGIC_SERVER
        private static ResLoader _resloader;
#endif
        public const string TableResPath = PathConstant.TableResPath;

        private static bool isEditorMode
        {
            get
            {
#if UNITY_EDITOR
                return !FrameworkEntry.Res;
#else
                return false;
#endif
            }
        }

        #region 通用
        public static TbCfgI18N i18n { get; private set; }
        public static TbCfgGlobal global { get; private set; }
        public static TbCfgText text { get; private set; }
        public static TbCfgErrorCode errorCode { get; private set; }
        public static TbCfgNotice notice { get; private set; }
        public static TbCfgResource resource { get; private set; }
        public static TbCfgAudio audio { get; private set; }
        public static TbCfgEntityBindPoint entityBindPoint { get; private set; }
        public static TbCfgCondition condition { get; private set; }
        public static TbCfgGmCmd gmCmd { get; private set; }
        public static TbCfgGmBatchCmd gmBatchCmd { get; private set; }

        public static TbCfgGmPanelList gmOutside { get; private set; }

        #endregion


        #region 系统相关

        public static TbCfgRoleRandomName roleRandomName { get; private set; }
        public static TbCfgRole role { get; private set; }
        public static TbCfgItem item { get; private set; }
        public static TbCfgFunctionType functionType { get; private set; }
        public static TbCfgSystemEffect systemEffect { get; private set; }
        public static TbCfgJump jump { get; private set; }
        public static TbCfgSoul soul { get; private set; }
        public static TbCfgHero hero { get; private set; }
        public static TbCfgHeroLevel heroLevel { get; private set; }
        public static TbCfgHeroSkin heroSkin { get; private set; }
        public static TbCfgHeroStar heroStar { get; private set; }
        public static TbCfgHeroAwaken heroAwaken { get; private set; }
        public static TbCfgHeroFateTrajectory heroFateTrajectory { get; private set; }
        public static TbCfgEquipLevel equipLevel { get; private set; }
        public static TbCfgEquipStar equipStar { get; private set; }
        public static TbCfgEquipSkin equipSkin { get; private set; }

        public static TbCfgSoulSkin soulSkin { get; private set; }
        public static TbCfgStoryDialog storyDialog { get; private set; }
        public static TbCfgQuest quest { get; private set; }
        public static TbCfgMail mail { get; private set; }
        public static TbCfgQuestPhase questPhase { get; private set; }
        public static TbCfgMallType mallType { get; private set; }
        public static TbCfgMallItem mallItem { get; private set; }
        public static TbCfgMonthCard monthCard { get; private set; }
        public static TbCfgPet pet { get; private set; }
        public static TbCfgPetLevel petLevel { get; private set; }
        public static TbCfgPlayerAvatar playerAvatar { get; private set; }
        public static TbCfgPlayerAvatarFrame avatarFrame { get; private set; }
        public static TbCfgPlayerCoatOfArms playerCoatOfArms { get; private set; }
        public static TbCfgStoryNpc storyNpc { get; private set; }
        public static TbCfgNonLevelServiceUnit nonLevelServiceUnit { get; private set; }
        public static TbCfgNonLevelExecution nonLevelExecution { get; private set; }
        #endregion

        #region 主城

        public static TbCfgMainCityNpc mainCityNpc { get; private set; }

        #endregion

        #region 关卡表

        public static TbCfgLevel level { get; private set; }
        public static TbCfgPhysicalEntity physicalEntity { get; private set; }
        public static TbCfgRegionInstance regionInstance { get; private set; }
        public static TbCfgScene scene { get; private set; }
        public static TbCfgLevelParam levelParam { get; private set; }
        public static TbCfgLevelEntityBubble levelEntityBubble { get; private set; }
        public static TbCfgLevelEntityBubbleGroup levelEntityBubbleGroup { get; private set; }
        public static TbCfgLevelScreenSwitch levelScreenSwitch { get; private set; }
        public static TbCfgEntityAnimAction entityAnimAction { get; private set; }
        public static TbCfgLevelEntityState levelEntityState { get; private set; }
        public static TbCfgLevelEntityInfo levelEntityInfo { get; private set; }

        public static TbCfgLevelCamera levelCamera { get; private set; }
        public static TbCfgLevelSceneEffect levelSceneEffect { get; private set; }
        public static TbCfgLevelRoutineAct levelRoutineAct { get; private set; }
        public static TbCfgLevelBuff levelBuff { get; private set; }
        public static TbCfgEntityInteractType entityInteractType { get; private set; }
        public static TbCfgSceneGround sceneGround { get; private set; }
        public static TbCfgLevelEntityViewTriggerAction levelEntityViewTriggerAction { get; private set; }
        public static TbCfgMonsterTeamGroup monsterTeamGroup { get; private set; }
        public static TbCfgLevelDropLib levelDropLib { get; private set; }
        public static TbCfgLevelDropLibControl levelDropLibControl { get; private set; }
        public static TbCfgLevelItemSubmit levelItemSubmit { get; private set; }

        public static TbCfgLevelItemJudge levelItemJudge { get; private set; }

        public static TbCfgQuickBarItem quickBarItem { get; private set; }

        public static TbCfgPortablePart portablePart { get; private set; }

        public static TbCfgLevelDynamicKey levelDynamicKey { get; private set; }

        public static TbCfgMapUiEntity mapUiEntity { get; private set; }

        #endregion


        #region 战斗

        public static TbCfgBuff buff { get; private set; }
        public static TbCfgBuffEffect buffeffect { get; private set; }
        public static TbCfgFormula formula { get; private set; }
        public static TbCfgAttribute attribute { get; private set; }
        public static TbCfgPabilityAttribute pabilityAttribute { get; private set; }
        public static TbCfgSkill skill { get; private set; }
        public static TbCfgSkillLevel skillLevel { get; private set; }
        public static TbCfgMonster monster { get; private set; }
        public static TbCfgMonsterTeam monsterTeam { get; private set; }
        public static TbCfgMonsterAttrCorrect monsterAttrCorrect { get; private set; }
        public static TbCfgMonsterPowerType monsterPowerType { get; private set; }
        public static TbCfgBattleScene battleScene { get; private set; }
        public static TbCfgBattleMorphs battleMorphs { get; private set; }
        public static TbCfgBattleAIMove battleAIMove { get; private set; }

        #endregion


        /// <summary>
        /// 加载所有table
        /// </summary>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
#if LOGIC_SERVER
       public static void LoadTables()
        {
#else
        public static async UniTask LoadTables()
        {
            _resloader = ResLoader.Create();
            // 持有住ab，防止频繁Unload(true)，最后统一Unload(true)，加载单个TextAsset完之后直接释放

#if UNITY_EDITOR
            if (isEditorMode)
            {
            }
            else
#endif
            {
                _resloader.LoadAssetBundle(TableResPath.Remove(TableResPath.Length - 1) +
                                           FramePathConsts.AssetBundleExtension);
            }
#endif
            Func<string, ByteBuf> loadFunc = LoadTableInternal;

            try
            {
                // i18n
                i18n = TbCfgI18N.LoadFromFunc(loadFunc);
                global = TbCfgGlobal.LoadFromFunc(loadFunc);

                #region 加载tables

                //通用开始---------------------------------
                text = TbCfgText.LoadFromFunc(loadFunc);
                errorCode = TbCfgErrorCode.LoadFromFunc(loadFunc);
                notice = TbCfgNotice.LoadFromFunc(loadFunc);
                resource = TbCfgResource.LoadFromFunc(loadFunc);
                audio = TbCfgAudio.LoadFromFunc(loadFunc);
                entityBindPoint = TbCfgEntityBindPoint.LoadFromFunc(loadFunc);
                gmCmd = TbCfgGmCmd.LoadFromFunc(loadFunc);
                gmBatchCmd = TbCfgGmBatchCmd.LoadFromFunc(loadFunc);
                gmOutside = TbCfgGmPanelList.LoadFromFunc(loadFunc);
                playerAvatar = TbCfgPlayerAvatar.LoadFromFunc(loadFunc);
                avatarFrame = TbCfgPlayerAvatarFrame.LoadFromFunc(loadFunc);
                playerCoatOfArms = TbCfgPlayerCoatOfArms.LoadFromFunc(loadFunc);
#if !LOGIC_SERVER
                await UniTask.Yield();
#endif
                //通用结束---------------------------------


                // ------------------- 系统 begin ------------------
                roleRandomName = TbCfgRoleRandomName.LoadFromFunc(loadFunc);
                role = TbCfgRole.LoadFromFunc(loadFunc);
                item = TbCfgItem.LoadFromFunc(loadFunc);
                functionType = TbCfgFunctionType.LoadFromFunc(loadFunc);
                systemEffect = TbCfgSystemEffect.LoadFromFunc(loadFunc);
                jump = TbCfgJump.LoadFromFunc(loadFunc);
                hero = TbCfgHero.LoadFromFunc(loadFunc);
                heroLevel = TbCfgHeroLevel.LoadFromFunc(loadFunc);
                heroSkin = TbCfgHeroSkin.LoadFromFunc(loadFunc);
                heroStar = TbCfgHeroStar.LoadFromFunc(loadFunc);
                heroAwaken = TbCfgHeroAwaken.LoadFromFunc(loadFunc);
                heroFateTrajectory = TbCfgHeroFateTrajectory.LoadFromFunc(loadFunc);
                equipLevel = TbCfgEquipLevel.LoadFromFunc(loadFunc);
                equipStar = TbCfgEquipStar.LoadFromFunc(loadFunc);
                equipSkin = TbCfgEquipSkin.LoadFromFunc(loadFunc);
                soul = TbCfgSoul.LoadFromFunc(loadFunc);
                soulSkin = TbCfgSoulSkin.LoadFromFunc(loadFunc);
                storyDialog = TbCfgStoryDialog.LoadFromFunc(loadFunc);
                quest = TbCfgQuest.LoadFromFunc(loadFunc);
                mail = TbCfgMail.LoadFromFunc(loadFunc);
                questPhase = TbCfgQuestPhase.LoadFromFunc(loadFunc);
                mallItem = TbCfgMallItem.LoadFromFunc(loadFunc);
                mallType = TbCfgMallType.LoadFromFunc(loadFunc);
                monthCard = TbCfgMonthCard.LoadFromFunc(loadFunc);
                pet = TbCfgPet.LoadFromFunc(loadFunc);
                petLevel = TbCfgPetLevel.LoadFromFunc(loadFunc);
                storyNpc = TbCfgStoryNpc.LoadFromFunc(loadFunc);
                nonLevelServiceUnit = TbCfgNonLevelServiceUnit.LoadFromFunc(loadFunc);
                nonLevelExecution = TbCfgNonLevelExecution.LoadFromFunc(loadFunc);
#if !LOGIC_SERVER
                await UniTask.Yield();
#endif
                // ------------------- 系统 end ------------------


                // ------------------- 主城 begin ------------------
                mainCityNpc = TbCfgMainCityNpc.LoadFromFunc(loadFunc);
                // ------------------- 主城 end ------------------
#if !LOGIC_SERVER
                await UniTask.Yield();
#endif

                //关卡开始---------------------------------
                level = TbCfgLevel.LoadFromFunc(loadFunc);
                physicalEntity = TbCfgPhysicalEntity.LoadFromFunc(loadFunc);
                regionInstance = TbCfgRegionInstance.LoadFromFunc(loadFunc);
                scene = TbCfgScene.LoadFromFunc(loadFunc);
                levelParam = TbCfgLevelParam.LoadFromFunc(loadFunc);
                condition = TbCfgCondition.LoadFromFunc(loadFunc);
                levelEntityBubble = TbCfgLevelEntityBubble.LoadFromFunc(loadFunc);
                levelEntityBubbleGroup = TbCfgLevelEntityBubbleGroup.LoadFromFunc(loadFunc);
                levelScreenSwitch = TbCfgLevelScreenSwitch.LoadFromFunc(loadFunc);
                entityAnimAction = TbCfgEntityAnimAction.LoadFromFunc(loadFunc);
                levelEntityState = TbCfgLevelEntityState.LoadFromFunc(loadFunc);
                levelEntityInfo = TbCfgLevelEntityInfo.LoadFromFunc(loadFunc);
                levelCamera = TbCfgLevelCamera.LoadFromFunc(loadFunc);
                levelSceneEffect = TbCfgLevelSceneEffect.LoadFromFunc(loadFunc);
                levelRoutineAct = TbCfgLevelRoutineAct.LoadFromFunc(loadFunc);
                levelBuff = TbCfgLevelBuff.LoadFromFunc(loadFunc);
                entityInteractType = TbCfgEntityInteractType.LoadFromFunc(loadFunc);
                sceneGround = TbCfgSceneGround.LoadFromFunc(loadFunc);
                levelEntityViewTriggerAction = TbCfgLevelEntityViewTriggerAction.LoadFromFunc(loadFunc);
                monsterTeamGroup = TbCfgMonsterTeamGroup.LoadFromFunc(loadFunc);
                levelDropLib = TbCfgLevelDropLib.LoadFromFunc(loadFunc);
                levelDropLibControl = TbCfgLevelDropLibControl.LoadFromFunc(loadFunc);
                levelItemSubmit = TbCfgLevelItemSubmit.LoadFromFunc(loadFunc);
                levelItemJudge = TbCfgLevelItemJudge.LoadFromFunc(loadFunc);
                quickBarItem = TbCfgQuickBarItem.LoadFromFunc(loadFunc);
                portablePart = TbCfgPortablePart.LoadFromFunc(loadFunc);
                levelDynamicKey = TbCfgLevelDynamicKey.LoadFromFunc(loadFunc);
                mapUiEntity = TbCfgMapUiEntity.LoadFromFunc(loadFunc);
#if !LOGIC_SERVER
                await UniTask.Yield();
#endif
                //关卡结束---------------------------------

                //战斗开始---------------------------------
                buff = TbCfgBuff.LoadFromFunc(loadFunc);
                buffeffect = TbCfgBuffEffect.LoadFromFunc(loadFunc);
                formula = TbCfgFormula.LoadFromFunc(loadFunc);
                attribute = TbCfgAttribute.LoadFromFunc(loadFunc);
                pabilityAttribute = TbCfgPabilityAttribute.LoadFromFunc(loadFunc);
                skill = TbCfgSkill.LoadFromFunc(loadFunc);
                skillLevel = TbCfgSkillLevel.LoadFromFunc(loadFunc);
                monster = TbCfgMonster.LoadFromFunc(loadFunc);
                monsterTeam = TbCfgMonsterTeam.LoadFromFunc(loadFunc);
                monsterAttrCorrect = TbCfgMonsterAttrCorrect.LoadFromFunc(loadFunc);
                monsterPowerType = TbCfgMonsterPowerType.LoadFromFunc(loadFunc);
                battleScene = TbCfgBattleScene.LoadFromFunc(loadFunc);
                battleMorphs = TbCfgBattleMorphs.LoadFromFunc(loadFunc);
                battleAIMove = TbCfgBattleAIMove.LoadFromFunc(loadFunc);
                // battleUnit = TbCfgBattleUnit.LoadFromFunc(loadFunc);
#if !LOGIC_SERVER
                await UniTask.Yield();
#endif
                //战斗结束---------------------------------

                //同步加载即可，多了可以借用await分帧加载
                //#if !LOGIC_SERVER
                //await UniTask.Yield();
                //#endif

                #endregion
            }
            catch (Exception e)
            {
                throw new Exception("读取配置表异常，请重新导表。exception:" + e.ToString());
            }
#if !LOGIC_SERVER
            // 卸载资源
            _resloader?.Put2Pool();
            _resloader = null;

            InjectTableVisitor2Framework();
#endif
        }

#if !LOGIC_SERVER
        /// <summary>
        /// 注入访问器到框架层
        /// </summary>
        private static void InjectTableVisitor2Framework()
        {
            AudioManager.TableVisitorAudio = (int id, out string cueName, out string sheetName,
                out AudioSourceType audioSourceType, out string selector, out string label) =>
            {
                var cfg = audio.Get(id);
                if (cfg == null)
                {
                    cueName = null;
                    sheetName = null;
                    audioSourceType = AudioSourceType.None;
                    selector = null;
                    label = null;
                    return false;
                }

                cueName = cfg.Cue;
                sheetName = cfg.Sheet;
                audioSourceType = (AudioSourceType)cfg.Type;
                selector = cfg.Selector;
                label = cfg.Label;
                return true;
            };
        }
#endif
        private static ByteBuf LoadTableInternal(string tableName)
        {
#if !LOGIC_SERVER
#if UNITY_EDITOR
            if (isEditorMode)
            {
                byte[] bytes =
                    System.IO.File.ReadAllBytes(Application.dataPath + "/" + TableResPath + tableName + ".bytes");
                return new ByteBuf(bytes);
            }
#endif
            var resloader = ResLoader.Create();
            var textAsset = resloader.LoadABAsset<TextAsset>(TableResPath + tableName + ".bytes");
            ByteBuf buff = new ByteBuf(textAsset.bytes);
            resloader.Put2Pool();
            return buff;
#else
            return LoadTableFormFile(tableName);
#endif
        }

        private static ByteBuf LoadTableFormFile(string tableName)
        {
            byte[] bytes = System.IO.File.ReadAllBytes(TableResPath + tableName + ".bytes");
            ByteBuf buff = new ByteBuf(bytes);
            return buff;
        }

        public static string GetI18NText(int id)
        {
            var data = i18n.GetWithoutError(id);
            if (data == null)
            {
                return string.Empty;
            }

            if (data.RefId > 0)
            {
                return GetI18NText(data.RefId);
            }

            return data.Str;
        }
    }
}
